package com.wyh.service.serviceImpl.appservieripml;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wyh.common.exception.BillNotFoundException;
import com.wyh.common.exception.CustomException;
import com.wyh.common.utils.SubStringFourUtils;
import com.wyh.domain.dto.groupfour.customerDTO.AddInvoiceHeaderDTO;
import com.wyh.domain.dto.groupfour.customerDTO.UpdateInvoiceHeaderDTO;
import com.wyh.domain.dto.depositDTO.DepositHistoryByIdDTO;
import com.wyh.domain.dto.depositDTO.DepositHistoryDTO;
import com.wyh.domain.vo.gruopfour.myProprietorVO.DepositVO;
import com.wyh.domain.vo.gruopfour.myProprietorVO.MyPaymentRecordVO;
import com.wyh.domain.vo.gruopfour.myProprietorVO.PayDataVO;
import com.wyh.domain.vo.gruopfour.myProprietorVO.SpecialBalanceVO;
import com.wyh.domain.vo.gruopfour.myVO.*;

import com.wyh.domain.vo.gruopfour.threemeterVO.PageResult;
import com.wyh.mapper.appmapper.MyMapper;
import com.wyh.service.appservice.IMyService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import static com.wyh.common.enums.MyProprietorEnum.*;
import static com.wyh.common.enums.ResultCodeEnum.*;

@Service
@Slf4j
public class MyServiceImpl implements IMyService {


    @Autowired
    private MyMapper myMapper;


    @Autowired
    private MyProprietorServiceImpl myProprietorService;


    @Override
    public PageResult<PayDataVO> getPayData(Integer customerId, Integer pageNum, Integer pageSize) {
        // 参数校验
        if (customerId == null) {
            log.error("Input parameter 'id' is null.");
            throw new CustomException(PARAM_LOST_ERROR.getCode(), PARAM_LOST_ERROR.getMsg());
        }
        // 使用PageHelper设置分页参数
        PageHelper.startPage(pageNum, pageSize);
        try {
            List<PayDataVO>  payDataList = myMapper.getPayData(customerId);
            for (PayDataVO payData : payDataList) {
                if (payData.getReceivable()-payData.getArrears()==0){
                    payData.setIsSettled(UNPAID.getCode());
                    System.out.println(payData.getIsSettled());
                }
                else if (payData.getTotalArrears()==0){
                    payData.setIsSettled(PAID.getCode());
                }
                else if (payData.getReceivable()-payData.getTotalArrears()>0){
                    payData.setIsSettled(PARTIALLY_PAID.getCode());
                }
            }
            // 使用PageInfo包装结果，以便获取总记录数
            PageInfo<PayDataVO> pageInfo = new PageInfo<>(payDataList);

            // 构建并返回PageResult对象
            return new PageResult<>(pageInfo.getTotal(), pageInfo.getList());
        } catch (Exception e) {
            log.error("Failed to get pay data for id {}: {}", customerId, e.getMessage());
            throw new RuntimeException("Error fetching pay data", e);
        }


//
//        return payDataList != null ? payDataList : new ArrayList<>();
    }

    @Override
    public BillInformationVO getBillData(Integer id) {
        BillInformationVO billData = null;
        billData = myMapper.getBillData(id);
        if (billData == null) {
            throw new BillNotFoundException(PROJECT_FIND_ERROR.getCode(), PROJECT_FIND_ERROR.getMsg());
        }
        try {
            billData.setPrepaidDeduction(myMapper.getPrepaidAccountInformation(id));
            billData.setGeneralDeduction(myMapper.getGenerealAccountInformation(id));

            billData.setActualPayment(billData.getReceivable() - billData.getPrepaidDeduction() - billData.getGeneralDeduction()-billData.getPendingAmount());

                if (billData.getActualPayment()==0){
                    billData.setIsSettled(UNPAID.getCode());
                    System.out.println(billData.getIsSettled());
                }
                else if (billData.getPendingAmount()==0){
                    billData.setIsSettled(PAID.getCode());
                }
                else if (billData.getReceivable()-billData.getPendingAmount()>0) {
                    billData.setIsSettled(PARTIALLY_PAID.getCode());
                }

            // 使用日志框架记录日志
            log.info("Billes data: {}", billData);
        } catch (Exception e) {
            log.error("Error fetching bill data for ID: {}", id, e);
            throw  new BillNotFoundException(PROJECT_FIND_ERROR.getCode(),PROJECT_FIND_ERROR.getMsg());
            // 处理异常，如设置返回值为null或错误码
            // 此处根据实际需求决定是否需要抛出自定义异常或如何处理此异常
        }

        return billData;
    }


    @Override
    public PageResult<MyPaymentRecordVO> getPaymentRecord(Integer customerId, Integer pageNum, Integer pageSize) {
        // 使用PageHelper设置分页参数
        PageHelper.startPage(pageNum, pageSize);
        List<MyPaymentRecordVO> myPaymentRecordVO = myMapper.getPaymentRecord(customerId);
        // 使用PageInfo包装结果，以便获取总记录数
        PageInfo<MyPaymentRecordVO> pageInfo = new PageInfo<>(myPaymentRecordVO);
        return  new PageResult<>(pageInfo.getTotal(), pageInfo.getList());
    }

    @Override
    public PageResult<InvoiceHeaderVO> getInvoiceHeaderList(Integer id, Integer pageNum, Integer pageSize) {
        // 参数校验
        if (id == null || id < 0) {
            // 参数不合法时，返回空列表而不是null
            return new PageResult<InvoiceHeaderVO>(0L, Collections.emptyList());
        }
        // 使用PageHelper设置分页参数
        PageHelper.startPage(pageNum, pageSize);

        try {
            // 尝试从mapper获取发票头信息列表
            List<InvoiceHeaderVO> invoiceHeaderList = myMapper.getInvoiceHeaderList(id);
            if (invoiceHeaderList == null) {
                // 如果返回null，转换为空列表
                invoiceHeaderList = Collections.emptyList();
            }
            // 使用PageInfo包装结果，以便获取总记录数
            PageInfo<InvoiceHeaderVO> pageInfo = new PageInfo<>(invoiceHeaderList);

            // 构建并返回PageResult对象
            return new PageResult<>(pageInfo.getTotal(), pageInfo.getList());
        } catch (Exception e) {
            // 异常处理，例如记录日志
             log.error("获取发票头信息列表失败", e);
            // 这里可以选择返回空列表或特定错误代码，以保持接口的简单性
            return new PageResult<>(0L, Collections.emptyList());
        }
    }

    @Override
    public String addInvoiceHeader(AddInvoiceHeaderDTO invoiceheader) {
        myMapper.addInvoiceHeader(invoiceheader);
        return "新增成功";
    }

    @Override
    public String updateInvoiceHeader(UpdateInvoiceHeaderDTO invoiceheader) {
        myMapper.updateInvoiceHeader(invoiceheader);
        return "修改成功";
    }

    @Override
    public List<BillDetailsVO> getBillDetails(Integer billId) {
        //建立一个空的List来存储结果
        List<BillDetailsVO> billDetailsList = new ArrayList<>();
        //获取账单id对应的资源id
        List<Integer> resourceId = myMapper.getBillDetailsResourceId(billId);
        //遍历资源id，获取对应的账单明细数据
        for (Integer id : resourceId) {
            //创建一个BillDetailsVO对象，并将账单明细数据添加到该对象中
            BillDetailsVO billDetailsVO = new BillDetailsVO();
            //获取账单明细数据
            List<BillDetailDataVO> billDetailData = myMapper.getBillDetails(id);
            //计算payable属性
            for(BillDetailDataVO billDetails : billDetailData){
                if (billDetails.getAccountsreceivable() != null && billDetails.getArrearsoffees() != null) {
                double payable = billDetails.getAccountsreceivable() - billDetails.getArrearsoffees()- billDetails.getPredepositoffset()
                        - billDetails.getVerificationAmount()- billDetails.getRefundDeduction();
                // 假设我们要增加的属性叫payable，这里需要确保BillDetailsVO类中已经定义了payable属性及其getter和setter
                billDetails.setPayable(payable);
            } else {
                // 如果有任一值为null，根据业务需求决定如何处理，这里简单设置为null或特定值
                billDetails.setPayable(null);
            }
        }
            //设置billDetailsVO对象的属性
            billDetailsVO.setBillDetailData(billDetailData);
            //设置billDetailsVO对象的属性
            billDetailsVO.setBillingResources(myMapper.getBillDetailsResourceName(id));
            //将billDetailsVO对象添加到列表中
            billDetailsList.add(billDetailsVO);
        }
        return billDetailsList;
    }


    /**
     * 获取保证金历史数据
     * @param
     * @return
     */
    @Override
    public List<DepositHistoryVO> getDepositHistory(DepositHistoryDTO depositHistoryDTO) {
        if (depositHistoryDTO.getResourceId() == null) {
            throw new IllegalArgumentException("Resourcees ID cannot be null");
        }


        try {
            List<DepositHistoryVO> depositHistoryVOList = myMapper.getDepositHistory(depositHistoryDTO);

            // 假设getConsumerResourceId是一个已经初始化的List<MasterDataContractVO>
            Optional<ContractVO> optionalContract = getConsumerResourceId.stream()
                    .filter(contractVO -> Objects.equals(contractVO.getResourceId(), depositHistoryDTO.getResourceId()))
                    .findFirst();

            if (!optionalContract.isPresent()) {
                throw new NoSuchElementException("No matching contract found for the given resource ID");
            }

            ContractVO contract = optionalContract.get();

            // 使用Stream API进行过滤，避免在遍历时修改集合
            List<DepositHistoryVO> filteredList = depositHistoryVOList.stream()
                    .filter(depositHistoryVO ->
                            !depositHistoryVO.getOptionTime().isBefore(contract.getCreateTime()) &&
                                    !depositHistoryVO.getOptionTime().isAfter(contract.getExpirationTime()))
                    .collect(Collectors.toList());

            return Collections.unmodifiableList(filteredList);
        } catch (Exception e) {
            // Log the exception using a proper logging framework
            // For simplicity, we're just printing to console here
            log.info("An error occurred while fetching deposit history: " + e.getMessage());
            return Collections.emptyList(); // Return an empty list in case of errors
        }
    }
    /**
     * 根据保证金类型查保证金历史数据
     * @param
     * @return
     */
    @Override
    public List<DepositHistoryVO> getDepositHistoryByType(DepositHistoryByIdDTO depositHistoryByIdDTO) {

        List<DepositHistoryVO> depositHistoryVOList = myMapper.getDepositHistoryByType(depositHistoryByIdDTO);
        ContractVO contract = new ContractVO();
        for (ContractVO contractVO : getConsumerResourceId){
            if (contractVO.getResourceId()==depositHistoryByIdDTO.getId()){
                contract = contractVO;
                System.out.println(contract);
            }
        }
        Iterator<DepositHistoryVO> iterator = depositHistoryVOList.iterator();
        while (iterator.hasNext()) {
            DepositHistoryVO depositHistoryVO = iterator.next();
            if (depositHistoryVO.getOptionTime().isBefore(contract.getCreateTime()) ||
                    depositHistoryVO.getOptionTime().isAfter(contract.getExpirationTime())) {
                iterator.remove();
            }
        }
        return depositHistoryVOList;
    }

    private static List<ContractVO> getConsumerResourceId;

    @Override
    public List<PrepaidAccountVO> getAccountResourceInformation(Integer id) {
        List<PrepaidAccountVO> prepaidAccountVOList = new ArrayList<>();
        //获取客户的资源id
            getConsumerResourceId = myMapper.getConsumerResourceId(id);
        for (ContractVO contract : getConsumerResourceId){
            Integer resourceId = contract.getResourceId();
            List<DepositVO> deposit = myProprietorService.getDeposit(contract.getResourceId());
            List<SpecialBalanceVO> specialBalance = myProprietorService.getSpecialBalance(contract.getResourceId());
            PrepaidAccountVO prepaidAccountVO = new PrepaidAccountVO(resourceId,SubStringFourUtils.subStringAfterNthSlashFromEnd(contract.getResourceName(),4,'/'), deposit,specialBalance);
            prepaidAccountVOList.add(prepaidAccountVO);
        }
        return prepaidAccountVOList;
    }

    // 获取资源id对应合同的时间
    private ContractVO findContractByResourceId(List<ContractVO> contracts, Integer resourceId) {
        // 检查contracts是否为空，避免NullPointerException
        if (contracts == null || contracts.isEmpty()) {
            return null; // 或者根据业务逻辑抛出异常，表示没有找到任何合同
        }

        for (ContractVO contract : contracts) {
            // 在比较前检查resourceId是否为null，避免NullPointerException
            if (resourceId == null || contract.getResourceId() == null) {
                continue; // 或者处理null值的情况，根据业务逻辑需要
            }
            if (contract.getResourceId().equals(resourceId)) {
                return contract;
            }
        }
        // 如果没有找到匹配的合同，返回null；考虑在文档中提醒调用方检查此返回值
        // 或者考虑抛出一个自定义异常，明确表示未找到对应的合同
        return null;
    }

    /**
     * 根据合约信息过滤资产变动历史记录。
     * 该方法用于筛选出与指定合约创建时间和到期时间范围匹配的资产变动历史记录。
     * 如果资产变动记录的时间早于合约创建时间或晚于合约到期时间，则认为该记录与合约不相关，将其从列表中移除。
     *
     * @param balanceHistories 资产变动历史记录列表。
     * @param contract         合约信息，包括合约的创建时间和到期时间。
     * @return 过滤后的资产变动历史记录列表，仅包含在合约有效时间内的记录。
     */
    private List<BalanceHistoryVO> filterBalanceHistoryByContract(List<BalanceHistoryVO> balanceHistories, ContractVO contract) {
        // 遍历资产变动历史记录列表
        Iterator<BalanceHistoryVO> iterator = balanceHistories.iterator();
        while (iterator.hasNext()) {
            BalanceHistoryVO history = iterator.next();
            // 检查资产变动记录的时间是否在合约的有效时间内
            if (history.getOptionTime().isBefore(contract.getCreateTime()) || history.getOptionTime().isAfter(contract.getExpirationTime())) {
                // 如果不在有效时间内，则从列表中移除该记录
                iterator.remove();
            }
        }
        // 返回过滤后的资产变动历史记录列表
        return balanceHistories;
    }


    @Override
    public List<BalanceHistoryVO> getGeneralBalanceHistory(Integer id) {
        List<BalanceHistoryVO> generalBalanceHistory = myMapper.getGeneralBalanceHistory(id);
        ContractVO ConsumerResourceId = findContractByResourceId(getConsumerResourceId, id);
        if (ConsumerResourceId != null) {
            return filterBalanceHistoryByContract(generalBalanceHistory, ConsumerResourceId);
        }
        return generalBalanceHistory; // 如果没找到对应的合同，可能需要处理这种情况
    }

    @Override
    public List<BalanceHistoryVO> getSpecialBalanceHistory(Integer id) {
        List<BalanceHistoryVO> specialBalanceHistory = myMapper.getSpecialBalanceHistory(id);
        ContractVO ConsumerResourceId = findContractByResourceId(getConsumerResourceId, id);
        if (ConsumerResourceId != null) {
            return filterBalanceHistoryByContract(specialBalanceHistory, ConsumerResourceId);
        }
        return specialBalanceHistory; // 同上，考虑未找到合同的处理
    }


}
